<script setup>
  import { ref, provide, computed, onMounted, watch } from 'vue'
  import { useForm, useField } from 'vee-validate'

  import { useCompanyConfigStore, useCompanyStore } from '@/stores/company'
  import {
    useFileStore,
    useCompanyLogoStore,
    useCompanyHeaderStore,
  } from '@/stores/files'

  import {
    formContextInjectionKey,
    getDefaults,
    buildYupSchema,
    getFieldData,
    getSubmitErrorCallback,
  } from '@/helpers/form'

  import Input from '@/components/forms/Input.vue'
  import DebugContent from '@/components/DebugContent.vue'

  import { getSubmitModelCallback } from '@/helpers/form'
  import Select from '@/components/forms/Select.vue'
  import CustomerSapComponent from '@/components/customer/sap/CustomerSapComponent.vue'
  import AddressInput from '@/components/customer/address/AddressInput.vue'
  import Select2 from '@/components/forms/Select2.vue'
  import ZipCodeCityInput from '@/components/customer/address/ZipCodeCityInput.vue'
  import IconSpan from '@/components/IconSpan.vue'
  import FileUpload from '@/components/forms/FileUpload.vue'
  import AutonomousImageUpload from '@/components/forms/AutonomousImageUpload.vue'
  import Accordion from '@/components/Accordion.vue'
  import RichTextArea from '@/components/forms/RichTextArea.vue'
  import BooleanCheckbox from '@/components/forms/BooleanCheckbox.vue'
  import LatLonMiniMap from '@/components/forms/LatLonMiniMap.vue'
  import { findAddress } from '@/helpers/apiGouv'
  import { DelayedLookupHandler } from '@/helpers/utils'
  import FormErrorList from '@/components/forms/FormErrorList.vue'

  const props = defineProps({
    company: { type: Object },
    layout: { type: Object },
  })
  const emit = defineEmits(['saved', 'cancel', 'error'])

  // DEBUG est définie globalement par webpack
  const debug = DEBUG
  const formConfigStore = useCompanyConfigStore()
  const companyStore = useCompanyStore()

  const activitiesOptions = ref(formConfigStore.getOptions('activities'))
  const decimalsToDisplayOptions = ref(
    formConfigStore.getOptions('decimal_to_display')
  )
  const depositOptions = ref(formConfigStore.getOptions('deposit_options'))
  const antennesOptions = ref(formConfigStore.getOptions('antennes_options'))
  const followerOptions = ref(formConfigStore.getOptions('follower_options'))

  const formSchema = computed(() => {
    console.log('Building form schema %s', 'default')
    const jsonSchema = formConfigStore.getSchema('default')
    console.log('Returning form schema')
    console.log(jsonSchema)
    return buildYupSchema(jsonSchema)
  })

  const initialValues = computed(() => {
    const result = getDefaults(formSchema.value)
    if (props.company) {
      Object.assign(result, props.company)
    }
    // Fill user_id from URL
    const preFilledUserId = new URLSearchParams(window.location.search).get(
      'user_id'
    )
    if (preFilledUserId) {
      result['user_id'] = preFilledUserId
    }
    return result
  })

  // Formulaire vee-validate (se met à jour automatiquement en fonction du schéma)
  const {
    values,
    handleSubmit,
    setFieldValue,
    isSubmitting,
    setFieldTouched,
    errors,
  } = useForm({
    validationSchema: formSchema,
    initialValues: initialValues,
  })
  const initialCollapsedState = ref(true)

  const onSubmitSuccess = getSubmitModelCallback(emit, (data) => {
    // Fill user_id from URL
    const preFilledUserId = new URLSearchParams(window.location.search).get(
      'user_id'
    )
    if (preFilledUserId) {
      data['user_id'] = preFilledUserId
    }
    return companyStore.saveCompany(data)
  })
  const onSubmitErrorCallback = () => (initialCollapsedState.value = false)
  const onSubmitError = getSubmitErrorCallback(emit, onSubmitErrorCallback)

  const onSubmit = handleSubmit(onSubmitSuccess, onSubmitError)
  const onCancel = () => emit('cancel')

  const onChangeLatLon = (latLon) => {
    if (!latLon) {
      latLon = { lat: null, lng: null }
    }
    setFieldValue('latitude', latLon.lat)
    setFieldTouched('latitude', true)
    setFieldValue('longitude', latLon.lng)
    setFieldTouched('longitude', true)
  }
  /** Handles attachments update via two fields
   *
   * @param id_field_name the field form name holding the id for the attachement FK
   * @param details_field_name the field holding the metadata (NodeFile JSON repr) fo the attachment
   * @param payload file metadata (NodeFile JSON repr)
   */
  const onAttachmentChange = function (
    id_field_name,
    details_field_name,
    payload
  ) {
    setFieldValue(id_field_name, payload ? payload.id : null)
    setFieldTouched(id_field_name, true)
    setFieldValue(details_field_name, payload)
    setFieldTouched(details_field_name, true)
  }
  // Utilitaire pour le rendu des champs : renvoie les attributs associés à un champ du formulaire
  const getFormFieldData = computed(
    () => (fieldName) => getFieldData(formSchema.value, fieldName)
  )

  // Met des informations du formulaire courant à disposition des composants enfants
  provide(formContextInjectionKey, {
    getFormFieldData: getFormFieldData,
    formSchema: formSchema,
    setFieldValue: (key, value) => {
      setFieldValue(key, value)
      setFieldTouched(key, true)
    },
  })

  // Configure le filestore des AutonomousImageUload
  const logoStore = useCompanyLogoStore()
  const headerStore = useCompanyHeaderStore()
  provide('fileStore-logo_id', logoStore)
  provide('fileStore-header_id', headerStore)

  const Layout = props.layout
  const isEditView = props.company && companyStore.companyId

  const initialLatLon = ref(
    isEditView ? [props.company.latitude, props.company.longitude] : null
  )

  const apiGouvLookupHandler = new DelayedLookupHandler((address, zip_code) =>
    findAddress(address, zip_code, 1)
  )

  /** If relevant, will query Address API and set lat / lon acoordingly
   *
   * You can fire it intensively (eg: type ahead), this function avoids
   * flooding the API using delays.
   *
   * It also does not use the results with little confidence score.
   */
  const setLatLonFromGeocoding = async (address, zip_code, city, country) => {
    if (
      (!country || country.toUpperCase() === 'FRANCE') &&
      address !== undefined
    ) {
      try {
        const lookup_pattern = city ? `${address}, ${city}` : address
        const results = await apiGouvLookupHandler.lookup(
          lookup_pattern,
          zip_code
        )
        if (results.length > 0) {
          const firstResult = results[0]
          const confidenceScore = firstResult.properties.score
          if (confidenceScore > 0.9) {
            console.log(
              `Setting map location because we have sufficient confidence in API result (score=${confidenceScore})`,
              firstResult
            )
            initialLatLon.value = firstResult.geometry.coordinates.toReversed()
          }
        }
      } catch (e) {
        // Most likely when a concurrent request is fired (previous one is cancelled)
        console.warn(e)
      }
    }
  }
  const showTechnicalAccordion = computed(() => {
    const fields = [
      'internal',
      'code_compta',
      'general_customer_account',
      'general_expense_account',
      'third_party_customer_account',
      'general_supplier_account',
      'third_party_supplier_account',
      'internalgeneral_customer_account',
      'internalthird_party_customer_account',
      'internalgeneral_supplier_account',
      'internalthird_party_supplier_account',
      'contribution',
      'internalcontribution',
      'insurance',
      'internalinsurance',
      'RIB',
      'IBAN',
      'antenne_id',
      'follower_id',
    ]
    return fields.some((field) => formSchema.value.fields[field] != undefined)
  })

  // Lookups the addresse.data.gouv.fr API on address type-ahead
  // If we are sufficiently confident in the result, change map location
  watch(
    () => [values.address, values.zip_code, values.city, values.country],
    async ([address, zip_code, city, country], _) => {
      await setLatLonFromGeocoding(address, zip_code, city, country)
    }
  )
</script>
<template>
  <div class="alert alert-success">
    <IconSpan name="success" alt="" />
    Les données de la section « <em>Informations publiques</em> » apparaissent
    sur les devis/factures, ainsi que dans l'annuaire et la carte des enseignes
    (accessibles seulement en interne, à tous les membres de la CAE).
  </div>

  <Layout @submitForm="onSubmit">
    <template v-slot:title>
      <template v-if="isEditView">Modifier l'enseigne</template>
      <template v-else>Ajouter une enseigne</template>
    </template>

    <template v-slot:fields>
      <div class="limited_width width60">
        <FormErrorList :errors="errors" :getFormFieldData="getFormFieldData" />
        <fieldset>
          <div id="form-accordion" class="collapsible">
            <Accordion :initial-collapsed-state="false">
              <template #title> Informations publiques </template>
              <template #body>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input v-bind="getFormFieldData('name')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input v-bind="getFormFieldData('goal')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Select2
                      v-bind="getFormFieldData('activities')"
                      :options="activitiesOptions"
                      :settings="{ multiple: true }"
                    />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input v-bind="getFormFieldData('email')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-6">
                    <Input v-bind="getFormFieldData('phone')" />
                  </div>
                  <div class="col-md-6">
                    <Input v-bind="getFormFieldData('mobile')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input v-bind="getFormFieldData('address')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-6">
                    <Input v-bind="getFormFieldData('zip_code')" />
                  </div>
                  <div class="col-md-6">
                    <Input v-bind="getFormFieldData('city')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input v-bind="getFormFieldData('country')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12 minimap">
                    <LatLonMiniMap
                      :fallbackCenter="[47.21297, -1.55104]"
                      :value="initialLatLon"
                      label="Position sur la carte des enseignes"
                      checkboxLabel="Publier la position"
                      checkboxDescription="Si « Publier la position » est activé, l'enseigne <strong>apparaîtra sur la carte des enseignes (interne  seulement)</strong>. Notez qu'il est possible d'apparaître sur la carte sans renseigner d'adresse (ex : pour <strong>éviter qu'une adresse perso n'apparaîsse sur les devis/factures</strong>) : il suffit de déplacer le marqueur manuellement et de vider les champs d'adresse."
                      @changeValue="onChangeLatLon"
                      @checkboxToggled="
                        (checked) =>
                          checked &&
                          setLatLonFromGeocoding(
                            values.address,
                            values.zip_code,
                            values.country
                          )
                      "
                    />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Input
                      v-bind="getFormFieldData('latitude')"
                      type="hidden"
                    />
                    <Input
                      v-bind="getFormFieldData('longitude')"
                      type="hidden"
                    />
                  </div>
                </div>

                <div class="row form-row">
                  <div class="col-md-12">
                    <AutonomousImageUpload
                      v-bind="getFormFieldData('logo_id')"
                      :file-info="values.logo"
                      :parent-id="companyStore.companyId"
                      @changeValue="
                        (payload) =>
                          onAttachmentChange('logo_id', 'logo', payload)
                      "
                    />
                  </div>
                </div>
              </template>
            </Accordion>
            <Accordion :initial-collapsed-state="initialCollapsedState">
              <template #title> Personnalisation des documents </template>
              <template #body>
                <div class="row form-row">
                  <div class="col-md-12">
                    <AutonomousImageUpload
                      v-bind="getFormFieldData('header_id')"
                      :file-info="values.header"
                      :parent-id="companyStore.companyId"
                      @changeValue="
                        (payload) =>
                          onAttachmentChange('header_id', 'header', payload)
                      "
                    />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <RichTextArea v-bind="getFormFieldData('cgv')" />
                  </div>
                </div>
                <div class="row form-row">
                  <div class="col-md-12">
                    <Select
                      v-bind="getFormFieldData('decimal_to_display')"
                      :options="decimalsToDisplayOptions"
                    />
                  </div>
                </div>

                <div
                  class="row form-row"
                  v-if="formSchema.fields.default_estimation_deposit"
                >
                  <div class="col-md-12">
                    <Select
                      v-bind="getFormFieldData('default_estimation_deposit')"
                      :options="depositOptions"
                    />
                  </div>
                </div>
                <div
                  class="row form-row"
                  v-if="
                    formSchema.fields.default_add_estimation_details_in_invoice
                  "
                >
                  <div class="col-md-12">
                    <BooleanCheckbox
                      v-bind="
                        getFormFieldData(
                          'default_add_estimation_details_in_invoice'
                        )
                      "
                    />
                  </div>
                </div>
              </template>
            </Accordion>

            <div v-if="showTechnicalAccordion">
              <Accordion :initial-collapsed-state="initialCollapsedState">
                <template #title>
                  Paramètres techniques (compta, gestion)
                </template>
                <template #body>
                  <div
                    class="row form-row"
                    v-if="formSchema.fields['internal']"
                  >
                    <div class="col-md-12">
                      <BooleanCheckbox v-bind="getFormFieldData('internal')" />
                    </div>
                  </div>
                  <template
                    v-for="account_field in [
                      'code_compta',
                      'general_customer_account',
                      'general_expense_account',
                      'third_party_customer_account',
                      'general_supplier_account',
                      'third_party_supplier_account',
                      'internalgeneral_customer_account',
                      'internalthird_party_customer_account',
                      'internalgeneral_supplier_account',
                      'internalthird_party_supplier_account',
                    ]"
                  >
                    <div
                      class="row form-row"
                      v-if="formSchema.fields[account_field]"
                    >
                      <div class="col-md-12">
                        <Input v-bind="getFormFieldData(account_field)" />
                      </div>
                    </div>
                  </template>

                  <template
                    v-for="percentage_field in [
                      'contribution',
                      'internalcontribution',
                      'insurance',
                      'internalinsurance',
                    ]"
                  >
                    <div
                      class="row form-row"
                      v-if="formSchema.fields[percentage_field]"
                    >
                      <div class="col-md-12">
                        <div class="input-group">
                          <Input
                            v-bind="getFormFieldData(percentage_field)"
                            :ariaLabel="
                              getFormFieldData(percentage_field).label +
                              ' (en pour-cents)'
                            "
                          />
                          <span class="input-group-addon">%</span>
                        </div>
                      </div>
                    </div>
                  </template>

                  <div class="row form-row" v-if="formSchema.fields.RIB">
                    <div class="col-md-12">
                      <Input v-bind="getFormFieldData('RIB')" />
                    </div>
                  </div>

                  <div class="row form-row" v-if="formSchema.fields.IBAN">
                    <div class="col-md-12">
                      <Input v-bind="getFormFieldData('IBAN')" />
                    </div>
                  </div>

                  <div class="row form-row" v-if="formSchema.fields.antenne_id">
                    <div class="col-md-12">
                      <Select
                        v-bind="getFormFieldData('antenne_id')"
                        :options="antennesOptions"
                      />
                    </div>
                  </div>

                  <div
                    class="row form-row"
                    v-if="formSchema.fields.follower_id"
                  >
                    <div class="col-md-12">
                      <Select2
                        v-bind="getFormFieldData('follower_id')"
                        :options="followerOptions"
                      />
                    </div>
                  </div>
                </template>
              </Accordion>
            </div>

            <div v-if="formSchema.fields.general_overhead">
              <Accordion :initial-collapsed-state="initialCollapsedState">
                <template #title>
                  Coefficient de calcul des études de prix
                </template>
                <template #body>
                  <div class="row form-row">
                    <div
                      class="col-md-6"
                      v-if="formSchema.fields.general_overhead"
                    >
                      <Input v-bind="getFormFieldData('general_overhead')" />
                    </div>
                    <div class="col-md-6" v-if="formSchema.fields.margin_rate">
                      <Input v-bind="getFormFieldData('margin_rate')" />
                    </div>
                  </div>

                  <div
                    class="row form-row"
                    v-if="formSchema.fields.use_margin_rate_in_catalog"
                  >
                    <div class="col-md-12">
                      <BooleanCheckbox
                        v-bind="getFormFieldData('use_margin_rate_in_catalog')"
                      />
                    </div>
                  </div>
                </template>
              </Accordion>
            </div>
          </div>
        </fieldset>
      </div>
    </template>

    <template v-slot:buttons>
      <button
        id="deformsubmit"
        name="submit"
        type="submit"
        class="btn btn-primary"
        value="submit"
        :disabled="isSubmitting"
      >
        Valider
      </button>
      <button
        id="deformcancel"
        name="cancel"
        type="button"
        class="btn btn-default"
        @click="onCancel"
      >
        Annuler
      </button>
      <DebugContent v-if="debug" :debug="values" />
    </template>
  </Layout>
</template>
